package com.example.myapplication.base.utils

import android.view.LayoutInflater
import androidx.databinding.ViewDataBinding
import java.lang.reflect.InvocationTargetException
import java.lang.reflect.ParameterizedType

object Utils {


    @Suppress("UNCHECKED_CAST")
    fun <DB : ViewDataBinding> createViewDataBinding(
        source: Any,
        layoutInflater: LayoutInflater
    ): DB? {
        var temp: Class<*>? = source.javaClass
        var z: Class<*>? = null
        while (z == null && null != temp) {
            z = getInstancedGenericKClass<ViewDataBinding>(temp)
            temp = temp.superclass
        }
        // 泛型擦除会导致z为null
        val db: DB? = if (z == null) {
            null
        } else {
            createBaseGenericKInstance(z, layoutInflater)
        }
        return db
    }

    private inline fun <reified T> getInstancedGenericKClass(z: Class<*>): Class<*>? {
        try {
            val type = z.genericSuperclass
            if (type is ParameterizedType) {
                val types = type.actualTypeArguments
                for (temp in types) {
                    if (temp is Class<*>) {
                        if (T::class.java.isAssignableFrom(temp)) {
                            return temp
                        }
                    } else if (temp is ParameterizedType) {
                        val rawType = temp.rawType
                        if (rawType is Class<*> && T::class.java.isAssignableFrom(
                                rawType
                            )
                        ) {
                            return rawType
                        }
                    }
                }
            }
        } catch (e: java.lang.reflect.GenericSignatureFormatError) {
            e.printStackTrace()
        } catch (e: TypeNotPresentException) {
            e.printStackTrace()
        } catch (e: java.lang.reflect.MalformedParameterizedTypeException) {
            e.printStackTrace()
        }
        return null
    }

    @Suppress("UNCHECKED_CAST")
    private fun <DB : ViewDataBinding> createBaseGenericKInstance(
        z: Class<*>,
        layoutInflater: LayoutInflater
    ): DB? {
        try {
            val m = z.getMethod("inflate", LayoutInflater::class.java)
            return m.invoke(null, layoutInflater) as DB
        } catch (e: NoSuchMethodException) {
            e.printStackTrace()
        } catch (e: IllegalAccessException) {
            e.printStackTrace()
        } catch (e: InstantiationException) {
            e.printStackTrace()
        } catch (e: InvocationTargetException) {
            e.printStackTrace()
        }

        return null
    }
}